package com.functest.orm

import com.functest.util.OrmUtil
import groovy.transform.ToString

/**
 * @author: DavydovMD
 * Date: 18.04.13
 * Time: 14:20
 */
@ToString(includeNames = true)
class Field {
    /**
     * Either String or list
     */
    String name
    List from
    /**
     * closure params: Field f, Map m
     * returns map with only one field name and value
     */
    Closure transform = MapperUtil.transform._default()
    /**
     * closure params: Field f, def value
     * returns map
     *
     */
    Closure<Map> transformBack = MapperUtil.transformBack._default()

    Field(Map params) {
        params.each {
            assert ['name', 'from', 'transform', 'transformBack'].contains(it.key), "unknown property $it"
        }
        name = params.name
        from = ((params.from != null) ? (params.from instanceof List ? params.from : [params.from]) : [params.name])
        if (params.transform) transform = params.transform
        if (params.transformBack) transformBack = params.transformBack

    }

    static boolean isSimpleName(String fieldName) {
        (!fieldName?.contains('.'))
    }

    static String simplifyName(String name) {
        OrmUtil.lastToken(name, '.')
    }

    /**
     * Important: unfortunately, despite of an attempt of make this a deep copy, copy might still include reference to current field in a closure
     * @param prefix
     * @return
     */
    Field copy() {
        copy('')
    }
    /**
     * Important: unfortunately, despite of an attempt of make this a deep copy, the copy might still include reference to current field in a closure
     * @param prefix
     * @return field's copy
     */
    Field copy(String prefix) {
        //TODO: Warning: this bounds closure to old field object!!! Find a way to fix it (how?!!!!)
        Field newField = new Field(name: (prefix ? prefix + this.name : this.name), from: new ArrayList(this.from), transform: this.transform, transformBack: this.transformBack)
        transform.delegate = newField
        newField
    }



    String getSimpleName() {
        simplifyName(name)
    }

    boolean equals(o) {
        if (o == null) return false
        if (this.is(o)) return true
        if (getClass() != o.class) return false

        Field field = (Field) o

        if (from != field.from) return false
        if (name != field.name) return false

        true
    }

    int hashCode() {
        int result
        result = name.hashCode()
        result = 31 * result + (from != null ? from.hashCode() : 0)
        result
    }

}